module Lockdown
  module ControllerInspector
    def all_methods(*ctrs)
      ctrs.collect{ |ctr| methods_for(ctr) }.flatten
    end
    
    def all_except_methods(ctr, *methods)
      methods_for(ctr) - methods.collect{|m| methods_for(ctr,m)}.flatten
    end
    
    def only_methods(ctr, *methods)
			methods.collect{|m| methods_for(ctr,m)}.flatten
    end
    
    def all_controllers
      all_actions = find_all_controller_classes
      
      all_actions.collect do |controller|
        methods ||= controller.public_instance_methods - controller.hidden_actions
        methods.collect{|method_name| controller.controller_path + "/" + method_name }
      end.flatten!
    end
    
    def methods_for(ctr, *methods)
      ctr = ctr.to_s if ctr.is_a?(Symbol)
      if methods.empty?
        klass = get_controller_class(ctr)
        methods = klass.public_instance_methods - klass.hidden_actions
      end
      methods.collect{|meth| ctr_path(ctr) + "/" + meth.to_s }
    rescue Exception => e
      raise e
      #rest_urls_for(ctr)
    end
    
    def rest_urls_for(ctr)
      ctr = ctr.to_s if ctr.is_a?(Symbol)
      rest_urls.collect{|url| ctr + "/" + url }
    end
    
    def rest_urls
      %w(index show new edit create update destroy)
    end
    
    private
			def ctr_path(ctr)
				ctr.gsub("__","\/")
      end

      def get_controller_class(ctr)
        load_controller(ctr)
        lockdown_const_get ctr
      end
      
      def load_controller(ctr)
        unless lockdown_const_defined? "Application"
          require(RAILS_ROOT + "/app/controllers/application.rb")
        end
        
        unless lockdown_const_defined? ctr
          require(RAILS_ROOT + "/app/controllers/#{kontroller_name(ctr)}_controller.rb")
        end
      end
      
      def find_all_controller_classes
        load_all_controllers
        return ObjectSpace.controller_classes
      end
      
      require "find"
      def load_all_controllers
        Find.find(File.join(RAILS_ROOT + '/app/controllers')) do |file_name|
          require(file_name) if /_controller.rb$/ =~ file_name
        end
      end
      
      def ObjectSpace.controller_classes
        subclasses = []
        self.each_object(Class) do |klass|
          subclasses << klass if klass.ancestors.include?(ApplicationController)
        end
        subclasses
      end
      
      def kontroller_name(ctr)
				if ctr.include?("__")
					ctr.split("__").join("/")
				else
					ctr
        end
			end

			def lockdown_const_defined?(str)
				if str.include?("__")
					parts = str.split("__")
					eval("#{parts[0].camelize}.const_defined?(\"#{parts[1].camelize}Controller\")") 
				else
					const_defined?(str.camelize)
        end
      end

			def lockdown_const_get(str)
				if str.include?("__")
					parts = str.split("__")
					eval("#{parts[0].camelize}.const_get(\"#{parts[1].camelize}Controller\")") 
				else
					const_get "#{str.camelize}Controller" 
        end
      end

      def klass_name(ctr)
				if ctr.include?("__")
					ctr = ctr.split("__").collect{|p| p.camelize}.join("::")
				else
					ctr = ctr.camelize
        end
        "#{ctr}Controller"
      end
  end # end ControllerInspector module
end
